#pragma once
//根据设计好的题库建立model，用来与用户进行数据交互
#include<iostream>
#include<vector>
#include<unordered_map>
#include<fstream>
#include<cassert>

#include"../Com/Log.hpp"
#include"../Com/Util.hpp"

namespace ns_model
{
    using namespace ns_LOG;
    using namespace ns_Util;
    const std::string questios_list = "./questions/questions.list";
    const std::string question_path = "./questions/";

    struct Question
    {
        std::string number; //题目编号，唯一
        std::string title;  //题目的标题
        std::string star;   //难度: 简单 中等 困难
        int cpu_limit;      //题目的时间要求(S)
        int mem_limit;      //题目的空间要求(KB)
        std::string desc;   //题目的描述
        std::string header; //题目预设给用户在线编辑器的代码
        std::string tail;   //题目的测试用例，需要和header拼接，形成完整代码
    };

    class Model
    {
    private:
        std::unordered_map<std::string, Question> questions; //题目编号和题目映射
    public:
        Model()
        {
            assert(LoadQuestionsList(questios_list));
        }

        ~Model(){}
    public:
        //加载题目列表
        bool LoadQuestionsList(const std::string& questions_list)
        {
            //打开题目列表文件
            std::ifstream in(questions_list);
            if(!in.is_open())
            {
                LOG(FATAL) << "打开题目列表失败!!!" << "\n";
                return false;
            }

            //逐行读取题目信息
            std::string line;
            while(std::getline(in, line))
            {
                //分割题目信息
                std::vector<std::string> tokens;
                FileUtil::SplitString(line, &tokens, " ");

                if(tokens.size() != 5)
                {
                    LOG(ERROR) << "读取部分题目信息失败！" << "\n";
                    return false;
                }

                //创建题目对象
                Question q;
                q.number = tokens[0];
                q.title = tokens[1];
                q.star = tokens[2];
                q.cpu_limit = std::stoi(tokens[3]);
                q.mem_limit = std::stoi(tokens[4]);

                //读取题目描述文件
                std::string file_path = question_path + q.number + "/";
                FileUtil::ReadFile(file_path + "desc.txt", &q.desc, true);
                FileUtil::ReadFile(file_path + "header.cpp", &q.header, true);
                FileUtil::ReadFile(file_path + "tail.cpp", &q.tail, true);

                //插入题目到题库
                questions.insert({q.number, q});
            }

            //关闭题目列表文件
            LOG(INFO) << "题目列表加载成功！" << "\n";
            // for(const auto &q : questions)
            // {
            //     std::cout << q.second.number << " " << q.second.title << " " << q.second.star << " " << q.second.cpu_limit << " " << q.second.mem_limit << "\n";
            // }
            in.close();
            return true;
        }

        //获取所有题目
        bool GetAllQuestions(std::vector<Question> *out)
        {
            if(questions.size() == 0)
            {
                LOG(ERROR) << "题库为空！" << "\n";
                return false;
            }

            for(const auto &q : questions)
            {

                out->push_back(q.second);
            }
            return true;
        }
        
        //获取指定题目
        bool GetQuestion(const std::string &number, Question *q)
        {
            auto iter = questions.find(number);
            if(iter == questions.end())
            {
                LOG(ERROR) << "题目" << number << "不存在！" << "\n";
                return false;
            }
            *q = iter->second;
            return true;
        }
    };
}